package com.newmainsoftech.dao.entity.relation;

import java.io.Serializable;
import java.lang.reflect.Proxy;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Transient;

@Entity
public class VariableHashHolderEntity implements HolderSideForTest<VariableHashHoldeeEntity>, Serializable {
	private static final long serialVersionUID = 1L;

	@Transient
	public static final String IdColumnName = "id";
		/** @return {@value #IdColumnName}
		 */
		public static String getIdColumnName() {
			return IdColumnName;
		}
	@Id
	@Basic( optional = false)
	@Column( name = VariableHashHolderEntity.IdColumnName)
	private String id;
		public String getId() {
			return id;
		}
		public void setId( final String id) {
			this.id = id;
		}
	
	@Transient
	boolean isEnsureIdentityCalled = false;
		public boolean isEnsureIdentityCalled() {
			return isEnsureIdentityCalled;
		}
		public void setEnsureIdentityCalled( boolean isEnsureIdentityCalled) {
			this.isEnsureIdentityCalled = isEnsureIdentityCalled;
		}

	@Override
	public void ensureIdentity() {
		setEnsureIdentityCalled( true);
	}
	
	@Transient
	private BiLinkCollectionProxy<VariableHashHolderEntity, VariableHashHoldeeEntity> biLinkCollectionProxy 
	= new EntityBiLinkCollectionProxyImpl<VariableHashHolderEntity, VariableHashHoldeeEntity>( this);
		public BiLinkCollectionProxy<VariableHashHolderEntity, VariableHashHoldeeEntity> 
			getBiLinkCollectionProxy() {
				return biLinkCollectionProxy;
			}
		public void setBiLinkCollectionProxy(
				final BiLinkCollectionProxy<VariableHashHolderEntity, VariableHashHoldeeEntity> 
					entityMediatorBaseCollectionProxy) {
			this.biLinkCollectionProxy = entityMediatorBaseCollectionProxy;
		}
		
	@OneToMany( targetEntity = VariableHashHoldeeEntity.class, mappedBy = "holderEntity", 
			cascade = { CascadeType.ALL}, orphanRemoval = true)
	private Collection<VariableHashHoldeeEntity> variableHashHoldees;
		/**
		 * {@inheritDoc}
		 * @return Collection of <code>{@link VariableHashHoldeeEntity}</code> entities linked to 
		 * this <code>{@link VariableHashHolderEntity}</code> entity.
		 */
		@Override
		public Collection<VariableHashHoldeeEntity> getHoldees() {
			if ( variableHashHoldees == null) {
				variableHashHoldees = new LinkedHashSet<VariableHashHoldeeEntity>();
			}
			return variableHashHoldees;
		}
		
		/**
		 * Main method for test: getter of <code>{@link VariableHashHoldeeEntity}</code> entity 
		 * collection what is actuallyproxy collection being obtained by 
		 * <code>{@link #getBiLinkCollectionProxy()}</code> method.<br />
		 * 
		 * @return proxy collection of <code>{@link VariableHashHoldeeEntity}</code> entities.
		 */
		@SuppressWarnings( "unchecked")
		public Collection<VariableHashHoldeeEntity> getVariableHashHoldees() {
			Object proxyObj 
			= Proxy.newProxyInstance( 
					this.getClass().getClassLoader(), 
					new Class<?>[]{ Collection.class}, 
					getBiLinkCollectionProxy());
			return Collections.synchronizedCollection( 
						(Collection<VariableHashHoldeeEntity>)proxyObj);
		}
		public void setVariableHashHoldees( final Collection<VariableHashHoldeeEntity> holdees) {
			this.variableHashHoldees = holdees;
		}
		@Override
		public Collection<VariableHashHoldeeEntity> getProxiedCollectionOfHoldees() {
			return getVariableHashHoldees();
		}
		
	@Transient
	private Collection<VariableHashHoldeeEntity> purgedHoldees;
		@Override
		public void setPurgedHoldees( final Collection<VariableHashHoldeeEntity> purgedHoldees) {
			this.purgedHoldees = purgedHoldees;
		}
		public Collection<VariableHashHoldeeEntity> getPurgedHoldees() {
			return purgedHoldees;
		}
		
	// hashCode and equals methods based on value of id member field ----------------------
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	@Override
	public boolean equals( final Object obj) {
		if ( this == obj) return true;
		if ( obj == null) return false;
		if ( getClass() != obj.getClass()) return false;
		
		VariableHashHolderEntity other = (VariableHashHolderEntity) obj;
		if (id == null) {
			if (other.id != null) return false;
		} 
		else if ( !id.equals(other.id)) return false;
		
		return true;
	}
	// ------------------------------------------------------------------------------------
		
	public VariableHashHolderEntity() {
		String idStr 
		= String.valueOf( Thread.currentThread().getId())
			.concat( "_").concat( String.valueOf( Calendar.getInstance().getTimeInMillis()))
			.concat( "_").concat( Integer.toHexString( System.identityHashCode( this)));
		setId( idStr);
			// As long as each test clean up every created VariableHashHolderEntity entities at end of 
			// test, this idStr value can assure uniqueness even in multi-threaded test environment.    
	}
	
	@Override
	public String toString() {
		return this.getClass().getSimpleName()
				.concat( "@" + Integer.toHexString( System.identityHashCode( this)))
				.concat( "[id=" + id)
				.concat( ", variableHashHoldees=")
					.concat( variableHashHoldees == null ? "null" : variableHashHoldees.toString())
				.concat( "]");
	}
	
	
}